﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecisionTree
{
    class LightDecisionTree
    {        
        public int InputLength { get; private set; }

        public int TrainError { get; private set; }

        public int TestError { get; private set; }

        public int? TreeIndex { get; private set; }

        public LightDecisionNode Root { get; private set; }

        public string LogString { get; private set; }

        public LightDecisionTree(int inputLength, int trainError, int testError, int? treeIndex, DecisionNode node, string logString)
        {
            this.InputLength = inputLength;
            this.TrainError = trainError;
            this.TestError = testError;
            this.TreeIndex = treeIndex;
            this.Root = node.ToLightDecisionNode(null);
            this.LogString = logString;
        }
        
        public byte Compute(byte[] p)
        {
            LightDecisionNode currentNode = this.Root;

            while (!currentNode.IsLeaf)
            {
                if(currentNode.IsValid(p))
                    currentNode = currentNode.Branches[0];
                else
                    currentNode = currentNode.Branches[1];
            }

            return (byte)currentNode.Output.Value;
        }

        public double[] ComputeWithHistogram(byte[] p)
        {
            LightDecisionNode currentNode = this.Root;

            while (!currentNode.IsLeaf)
            {
                if (currentNode.IsValid(p))
                    currentNode = currentNode.Branches[0];
                else
                    currentNode = currentNode.Branches[1];
            }

            return currentNode.OutputHistogram;
        }

        private void ComputeWithHistogramTolerancedRecursive(byte[] p, LightDecisionNode node, int error, double[] rVal)
        {
            if (error < 2)
            {
                if (node.IsLeaf)
                {
                    rVal[node.Output.Value] += node.IndexCount;
                }
                else
                {
                    if (node.IsValid(p))
                    {
                        ComputeWithHistogramTolerancedRecursive(p, node.Branches[0], error, rVal);
                        ComputeWithHistogramTolerancedRecursive(p, node.Branches[1], error + 1, rVal);
                    }
                    else
                    {
                        ComputeWithHistogramTolerancedRecursive(p, node.Branches[0], error + 1, rVal);
                        ComputeWithHistogramTolerancedRecursive(p, node.Branches[1], error, rVal);
                    }
                }
            }
        }

        public double[] ComputeWithHistogramToleranced(byte[] p)
        {
            double[] rVal = new double[10];

            ComputeWithHistogramTolerancedRecursive(p, this.Root, 0, rVal);

            return rVal;
        }
    }
}
